package com.homesoft.runtime.core.loaders;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;

public abstract class BusinessClassLoader {
	private static boolean classLoaderIsInitialized;
	private static IBusinessClassLoaderFactory factory;
	private static List<BusinessClassLoader> loaders = new ArrayList<BusinessClassLoader>();

	public static boolean getClassLoaderIsInitialized() {
		return classLoaderIsInitialized;
	}

	public static void setClassLoaderIsInitialized(boolean classLoaderIsInitialized) {
		BusinessClassLoader.classLoaderIsInitialized = classLoaderIsInitialized;
	}
	
	public static List<BusinessClassLoader> getLoaders() {
		return loaders;
	}

	public static void setLoaders(List<BusinessClassLoader> loaders) {
		BusinessClassLoader.loaders = loaders;
	}
	
	protected static IBusinessClassLoaderFactory getFactory() {
		return factory;
    }
    
	BusinessClassLoader()
    {
		classLoaderIsInitialized = false;
		factory = new DefaultBusinessClassLoaderFactory();
    }
	
	public static void InsertLoader(int index, BusinessClassLoader loader)
    {
		getLoaders().add(index, loader);
    }
	
	/**
	 * 获取实体元数据实体生成代码后的运行期的类型，如果没有则反回null
	 * @param metadataName
	 * @return
	 */
	public static Object getEntityRuntimeType(String metadataName) {
		Object obj = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			obj = loader.getEntityRuntimeTypeInternal(metadataName);
			
			if (obj != null) {
				break;
			}
		}
		
		return obj;
	}
	
	protected abstract Object getEntityRuntimeTypeInternal(String metadataName);
	
	/**
	 * 获取枚举元数据实体生成代码后的运行期的类型，如果没有则反回null
	 * @param metadataName
	 * @return
	 */
	public static Object getEnumRuntimeType(String metadataName) {
		Object obj = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			obj = loader.getEnumRuntimeTypeInternal(metadataName);
			
			if (obj != null) {
				break;
			}
		}
		
		return obj;
	}
	
	protected abstract Object getEnumRuntimeTypeInternal(String metadataName);
	
	/**
	 * 获取服务接口的实现类的实例
	 * @param serviceInterfaceType
	 * @return
	 */
	public static Object getService(Object serviceInterfaceType) {
		Object obj = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			obj = loader.getServiceInternal(serviceInterfaceType);
			
			if (obj != null) {
				break;
			}
		}
		
		return obj;
    }
	
	protected abstract Object getServiceInternal(Object serviceInterfaceType);
	
	/*不会写
	public static <T extends Object> T getServicepp(T t)
    {
        return GetService(t.getClass());
    }
    */
	
	/**
	 * 根据服务名称和实体名称获取服务接口定义类型
	 * @param metadataName
	 * @return
	 */
	public static Object getServiceInterfaceType(String metadataName)
    {
		Object obj = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			obj = loader.getServiceInterfaceTypeInternal(metadataName);
			
			if (obj != null) {
				break;
			}
		}
		
		return obj;
    }
	
	protected abstract Object getServiceInterfaceTypeInternal(String metadataName);
	
	/**
	 * 获取UIController的实例
	 * @param controllerName
	 * @return
	 */
	public static Object getUIController(String controllerName) {
		Object controller = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			controller = loader.getUIControllerInternal(controllerName);
			
			if (controller != null) {
				break;
			}
		}
		
		return controller;
    }
	
	protected abstract Object getUIControllerInternal(String controllerName);
	
	public static InputStream getMetadataStream(String metadataName) {
		InputStream stream = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			stream = loader.getMetadataStreamInternal(metadataName);
			
			if (stream != null) {
				break;
			}
		}
		
		return stream;
    }
	
	protected abstract InputStream getMetadataStreamInternal(String metadataName);
	
	public static InputStream getMetadataStream(String metadataName, LoadFolder folder) {
		InputStream stream = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			stream = loader.getMetadataStreamInternal(metadataName, folder);
			
			if (stream != null) {
				break;
			}
		}
		
		return stream;
    }
	
	protected abstract InputStream getMetadataStreamInternal(String metadataName, LoadFolder folder);
	
	static Enumeration<MetadataRuntimeInfo> getAllRuntimeMetadataInfos() {
		Enumeration<MetadataRuntimeInfo> info = null;
		
		for (BusinessClassLoader loader : getLoaders()) {
			info = loader.getAllRuntimeMetadataInfosInternal();
			
			if (info != null) {
				break;
			}
		}
		
		return info;
    }

    protected abstract Enumeration<MetadataRuntimeInfo> getAllRuntimeMetadataInfosInternal();
	
	/**
	 * 初始化Loader
	 */
	protected abstract void initInternal();
	
	/**
	 * 清理ClassLoader
	 */
	protected abstract void clearInternal();
	
	public static void Init() {
        if (!getClassLoaderIsInitialized()) {
        	getLoaders().clear();
        	BusinessClassLoader loader = getFactory().CreateClassLoader();
        	loader.initInternal();
        	getLoaders().add(loader);
        	setClassLoaderIsInitialized(true);
        }
    }
	
	public static void Clear() {
		setClassLoaderIsInitialized(false);
        List<BusinessClassLoader> loaders = getLoaders();
        
        for (BusinessClassLoader loader : loaders) {
        	loader.clearInternal();
        }
        loaders.clear();
    }
}
